diff options
Diffstat (limited to 'app/api/files/[...path]/route.ts')
| -rw-r--r-- | app/api/files/[...path]/route.ts | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/app/api/files/[...path]/route.ts b/app/api/files/[...path]/route.ts index 3fb60347..88211f5b 100644 --- a/app/api/files/[...path]/route.ts +++ b/app/api/files/[...path]/route.ts @@ -31,6 +31,7 @@ const getMimeType = (filePath: string): string => { const isAllowedPath = (requestedPath: string): boolean => { const allowedPaths = [ 'basicContract', + 'contracts', 'basicContract/template', 'basicContract/signed', 'vendorFormReportSample', @@ -64,7 +65,12 @@ export async function GET( ) { try { // 요청된 파일 경로 구성 - const requestedPath = params.path.join('/'); + const decodedPath = params.path.map(segment => + decodeURIComponent(segment) + ); + + // 디코딩된 경로로 조합 + const requestedPath = decodedPath.join('/'); console.log(`📂 파일 요청: ${requestedPath}`); @@ -124,10 +130,14 @@ export async function GET( console.log(`✅ 파일 서빙 성공: ${fileName} (${stats.size} bytes)`); - // ✅ Content-Disposition 헤더 결정 + const encodedFileName = encodeURIComponent(fileName) + .replace(/'/g, "%27") + .replace(/"/g, "%22"); + const contentDisposition = forceDownload - ? `attachment; filename="${fileName}"` // 강제 다운로드 - : `inline; filename="${fileName}"`; // 브라우저에서 열기 + ? `attachment; filename="${encodedFileName}"; filename*=UTF-8''${encodedFileName}` + : `inline; filename="${encodedFileName}"; filename*=UTF-8''${encodedFileName}`; + // Range 요청 처리 (큰 파일의 부분 다운로드 지원) const range = request.headers.get('range'); @@ -176,7 +186,12 @@ export async function HEAD( { params }: { params: { path: string[] } } ) { try { - const requestedPath = params.path.join('/'); + const decodedPath = params.path.map(segment => + decodeURIComponent(segment) + ); + + // 디코딩된 경로로 조합 + const requestedPath = decodedPath.join('/'); // ✅ HEAD 요청에서도 다운로드 강제 여부 확인 const url = new URL(request.url); @@ -207,11 +222,16 @@ export async function HEAD( const mimeType = getMimeType(filePath); const fileName = path.basename(filePath); - // ✅ HEAD 요청에서도 Content-Disposition 헤더 적용 - const contentDisposition = forceDownload - ? `attachment; filename="${fileName}"` // 강제 다운로드 - : `inline; filename="${fileName}"`; // 브라우저에서 열기 + const encodedFileName = encodeURIComponent(fileName) + .replace(/'/g, "%27") + .replace(/"/g, "%22"); + + const contentDisposition = forceDownload + ? `attachment; filename="${encodedFileName}"; filename*=UTF-8''${encodedFileName}` + : `inline; filename="${encodedFileName}"; filename*=UTF-8''${encodedFileName}`; + + return new NextResponse(null, { headers: { 'Content-Type': mimeType, |
